#ifndef __EXTERNAL_FORCE_INTERFACE_V1_1_0__
#define __EXTERNAL_FORCE_INTERFACE_V1_1_0__

#ifdef WIN32
	#ifdef __cplusplus
		#define EXPORT_MACRO extern "C" __declspec(dllexport)
	#else
		#define EXPORT_MACRO __declspec(dllexport)
	#endif
#else
	#ifdef __cplusplus
		#define EXPORT_MACRO extern "C"
	#else
		#define EXPORT_MACRO
	#endif
#endif

//Return values from EXTERNALFORCE
#define EF_SUCCESS                  0
#define EF_ERR_NO_PREFERENCES_FILE -1

//interface version info (not to be modified)
#define EF_INTERFACE_MAJOR_VERSION 0x01
#define EF_INTERFACE_MINOR_VERSION 0x01
#define EF_INTERFACE_SUB_VERSION   0x00

//size of strings passed into functions (not to be modified)
#define EF_PREF_FILE_BUFF_SIZE  128
#define EF_PROP_NAME_BUFF_SIZE 1024

// Macros for property data types
#define EF_PROP_DATA_TYPE_DOUBLE 0

// macros for property unit types
#define EF_PROP_UNIT_TYPE_OTHER                0
#define EF_PROP_UNIT_TYPE_NONE                 1
#define EF_PROP_UNIT_TYPE_ACCELERATION         2
#define EF_PROP_UNIT_TYPE_ANGLE                3
#define EF_PROP_UNIT_TYPE_ANGULAR_ACELERATION  4
#define EF_PROP_UNIT_TYPE_ANGULAR_VELOCITY     5
#define EF_PROP_UNIT_TYPE_DENSITY              6
#define EF_PROP_UNIT_TYPE_ENERGY               7
#define EF_PROP_UNIT_TYPE_WORK_FUNCTION        8
#define EF_PROP_UNIT_TYPE_FORCE                9
#define EF_PROP_UNIT_TYPE_CHARGE              10
#define EF_PROP_UNIT_TYPE_LENGTH              11
#define EF_PROP_UNIT_TYPE_MASS                12
#define EF_PROP_UNIT_TYPE_MOI                 13
#define EF_PROP_UNIT_TYPE_SHEAR_MOD           14
#define EF_PROP_UNIT_TYPE_TIME                15
#define EF_PROP_UNIT_TYPE_TORQUE              16
#define EF_PROP_UNIT_TYPE_VELOCITY            17
#define EF_PROP_UNIT_TYPE_VOLUME              18
#define EF_PROP_UNIT_TYPE_FREQUENCY           19
#define EF_PROP_UNIT_TYPE_TEMPERATURE         20
#define EF_PROP_UNIT_TYPE_HEAT_FLUX           21


/* This function should not be modified */
EXPORT_MACRO int GETEFINTERFACEVERSION()
{
	return (EF_INTERFACE_MAJOR_VERSION << 16 | EF_INTERFACE_MINOR_VERSION << 8 | EF_INTERFACE_SUB_VERSION);
}

/*
 * The following functions require to be implemented before your plugin
 * can be loaded and used:
 *
 * GETEFPREFERENCEFILE
 *     returns the name of the config file used by this contact model (if any)
 *
 * EXTERNALFORCE
 *     does the actual force calculation for the contact
 *
 * REGISTERNEWPARTICLEPROPERTY
 *     Called by Edem to inform the plugin of a new finalised custom property
 *
 * GETNUMBEROFREQUIREDPROPERTIES
 *     Called by Edem to query the number of custom properties required
 *     by this plugin to run.
 *
 * GETDETAILSFORPROPERTY
 *     Returns the details for the custom properties required for this plugin
 *     to run.
 *
 * If a plugin does not care about custom properties then the implementations of
 * REGISTERNEWPARTICLEPROPERTY, GETNUMBEROFREQUIREDPROPERTIES, and
 * GETDETAILSFORPROPERTY can be stubbed
 */

/**
 * Specifies the name of the config file used by the plugin.
 * @param caPrefFile (Return value) A character array to be populated with the
 *                   config file name.
 *                   This path is relative to the directory the plugin is stored in.
 */
EXPORT_MACRO void GETEFPREFERENCEFILE(char caPrefFile[EF_PREF_FILE_BUFF_SIZE]);

/**
 * This function is called every single time step for every single particle. It allows
 * the user to add an external force (e.g. electromagnetic force, drag force) to particles.
 * The following parameters are taken in by the function (and should not be altered):
 *
 * GENERAL INFORMATION
 * -------------------
 *
 * sPrefFile - name & location of the optional preferences file.
 * nTime     - the current simulation time
 * nTimeStep - the current simulation time step
 *
 * PARTICLE INFORMATION
 * -------------------
 *
 * nId           - the number id of the particle (these are unique)
 * sType         - a char * containing the particle prototype this surface was created from
 * nMass         - the mass
 * nVolume       - the volume
 * nPosX,Y,Z     - the x, y, z coordinates of the centroid
 * nVelX,Y,Z     - the x, y, z components of velocity
 * nAngVelX,Y,Z  - the x, y, z components of angular velocity
 * charge        - The particles charge
 * orientation   - A 9 element array containing the orientation matrix for this element
 *                 The elements of the array are in the following order:
 *                     XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ
 * propertyList  - Pointer to a double array containing the property list for the particle
 *
 * The following information concerns the magnitude of the forces and torques on the particle and should be filled
 * in by the user.
 *
 * FORCES & TORQUES
 * ----------------
 *
 * nForceX,Y,Z  - The x, y, z components of the external force on the particle. This force is taken to act at the particle centroid.
 * nTorqueX,Y,Z - The x, y, z components of the external torque on the particle. This torque is in global coordinates
 *
 * propertyListChanges - array of double values the same length as the corresponding propertyList
 *                       populated with deltas to the values where needed.
 *                       Unlike other parameters propertyListChanges1 may already contain data that we
 *                       do not want to loose (changes from prior calculations).  Do not
 *                       set this array to 0 and add or subtract your changes from the existing values
 *
 * The function should return a value to indicate success or failure (see error codes defined above).
 *
 * For additional information please see the help, or one of the examples included in with the product.
 */
EXPORT_MACRO int EXTERNALFORCE(const char *sPrefFile, double *nTime, double *nTimeStep,
                               int *nId, const char *sType,double *nMass,
                               double *nVolume, double *nPosX, double *nPosY, double *nPosZ,
                               double *nVelX, double *nVelY, double *nVelZ,
                               double* charge,
                               double *nAngVelX, double *nAngVelY, double *nAngVelZ,
                               double* orientation,
                               double* propertyList,
                               double *nForceX, double *nForceY, double *nForceZ,
                               double *nTorqueX, double *nTorqueY, double *nTorqueZ,
                               double *propertyListChanges);

/**
 * Registers a new finalised property with the plugin.
 * As each custom particle property becomes finalised (available for use) this
 * method will be called with the details of the property.  A plugin
 * cannot use a property until it has been registered with it via this method
 * For details of how properties are represented see the CALCULATEFORCE method
 *
 * If the plugin does not make use of custom properties this method can be
 * an empty stub that does nothing.
 *
 * @param name             The name of the property (null terminated string)
 * @param numberOfElements The number of elements in the property
 * @param dataType         The data type of the property, currently allways
 *                         EF_PROP_DATA_TYPE_DOUBLE
 * @param offset           The offset in a 1D property array to the first
 *                         element of the properties data.
 */
EXPORT_MACRO void REGISTERNEWPARTICLEPROPERTY(const char* name,
                                              unsigned int* numberOfElements,
                                              unsigned int* dataType,
                                              unsigned int* unitType,
                                              unsigned int* offset);
/**
 * Returns the number of custom properties this plugin wishes to
 * register with the system.
 *
 * If the plugin does not use custom properties this method should return 0.
 *
 * @return The number of custom properties the plugin wishes to
 *         register.
 */
EXPORT_MACRO unsigned int GETNUMBEROFREQUIREDPROPERTIES();

/**
 * Retrieves details for a given property.  This method can be
 * called for propertyIndex values 0...(GETNUMBEROFREQUIREDPROPERTIES() - 1) to
 * retrieve the details for that property from the plugin.  These properties
 * will then be registered with the system if they do not clash with any
 * existing properties.
 *
 * A plugin cannot make use of any properties, even those it registers, until
 * it has been informed of them via the REGISTERNEWPARTICLEPROPERTY method
 * as until then it does not know the offset to the property data.  The plugin
 * cannot assume the properties it regisers will appear in any specific order.
 *
 * If the plugin does not use custom properties this method should allways
 * return false
 *
 * @param propertyIndex    The index of the property to retrieve data for
 * @param name             (Return value) A EF_PROP_NAME_BUFF_SIZE char array
 *                         is supplied to be populated with the name of the
 *                         property
 * @param dataType         (Return value) Should allways be set to
 *                         EF_PROP_DATA_TYPE_DOUBLE
 * @param numberOfElements (Return value) The number of elements (min 1)
 * @param unitType         (Return value) The unit type of the property
 * @return bool to say if data exists for the property
 */
EXPORT_MACRO bool GETDETAILSFORPROPERTY(unsigned int* propertyIndex,
                                        char name[EF_PROP_NAME_BUFF_SIZE],
                                        unsigned int* dataType,
                                        unsigned int* numberOfElements,
                                        unsigned int* unitType);

#endif

